{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "from langchain import PromptTemplate, OpenAI, LLMChain\n",
    "\n",
    "load_dotenv(find_dotenv())\n",
    "openai.api_key = os.environ[\"OPENAI_API_KEY\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "template = \"\"\"\n",
    "Interprete the text and evaluate the text.\n",
    "sentiment: is the text in a positive, neutral or negative sentiment?\n",
    "subject: What subject is the text about? Use exactly one word.\n",
    "\n",
    "Format the output as JSON with the following keys:\n",
    "sentiment\n",
    "subject\n",
    "\n",
    "text: {input}\n",
    "\"\"\"\n",
    "\n",
    "llm = OpenAI(temperature=0)\n",
    "prompt_template = PromptTemplate.from_template(template=template)\n",
    "chain = LLMChain(llm=llm, prompt=prompt_template)\n",
    "chain.predict(input=\"I ordered Pizza Salami and it was awesome!\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sequentials Chains\n",
    "Sometimes you want to pass the output from one model to a another model. This can be done with different SequentialsChains"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "response_template = \"\"\"\n",
    "You are a helpful bot that creates a 'thank you' reponse text. \n",
    "If customers are unsatisfied, offer them a real world assitant to talk to. \n",
    "You will get a sentiment and subject as into and evaluate. \n",
    "\n",
    "text: {input}\n",
    "\"\"\"\n",
    "review_template = PromptTemplate(input_variables=[\"input\"], template=response_template)\n",
    "review_chain = LLMChain(llm=llm, prompt=review_template)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import SimpleSequentialChain\n",
    "\n",
    "overall_chain = SimpleSequentialChain(chains=[chain, review_chain], verbose=True)\n",
    "\n",
    "overall_chain.run(input=\"I ordered Pizza Salami and was aweful!\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Chains can be more complex and not all sequential chains will be as simple as passing a single string as an argument and getting a single string as output for all steps in the chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.chains import SequentialChain\n",
    "\n",
    "# This is an LLMChain to write a review given a dish name and the experience.\n",
    "prompt_review = PromptTemplate.from_template(\n",
    "    template=\"You ordered {dish_name} and your experience was {experience}. Write a review: \"\n",
    ")\n",
    "chain_review = LLMChain(llm=llm, prompt=prompt_review, output_key=\"review\")\n",
    "\n",
    "# This is an LLMChain to write a follow-up comment given the restaurant review.\n",
    "prompt_comment = PromptTemplate.from_template(\n",
    "    template=\"Given the restaurant review: {review}, write a follow-up comment: \"\n",
    ")\n",
    "chain_comment = LLMChain(llm=llm, prompt=prompt_comment, output_key=\"comment\")\n",
    "\n",
    "# This is an LLMChain to summarize a review.\n",
    "prompt_summary = PromptTemplate.from_template(\n",
    "    template=\"Summarise the review in one short sentence: \\n\\n {review}\"\n",
    ")\n",
    "chain_summary = LLMChain(llm=llm, prompt=prompt_summary, output_key=\"summary\")\n",
    "\n",
    "# This is an LLMChain to translate a summary into German.\n",
    "prompt_translation = PromptTemplate.from_template(\n",
    "    template=\"Translate the summary to german: \\n\\n {summary}\"\n",
    ")\n",
    "chain_translation = LLMChain(\n",
    "    llm=llm, prompt=prompt_translation, output_key=\"german_translation\"\n",
    ")\n",
    "\n",
    "overall_chain = SequentialChain(\n",
    "    chains=[chain_review, chain_comment, chain_summary, chain_translation],\n",
    "    input_variables=[\"dish_name\", \"experience\"],\n",
    "    output_variables=[\"review\", \"comment\", \"summary\", \"german_translation\"],\n",
    ")\n",
    "\n",
    "overall_chain({\"dish_name\": \"Pizza Salami\", \"experience\": \"It was awful!\"})"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instead of chaining multiple chains together we can also use an LLM to decide which follow up chain is being used"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.llms import OpenAI\n",
    "from langchain.chains.router import MultiPromptChain\n",
    "from langchain.chains.llm import LLMChain\n",
    "from langchain.prompts import PromptTemplate\n",
    "from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser\n",
    "from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE\n",
    "\n",
    "positive_template = \"\"\"You are an AI that focuses on the positive side of things. \\\n",
    "Whenever you analyze a text, you look for the positive aspects and highlight them. \\\n",
    "Here is the text:\n",
    "{input}\"\"\"\n",
    "\n",
    "neutral_template = \"\"\"You are an AI that has a neutral perspective. You just provide a balanced analysis of the text, \\\n",
    "not favoring any positive or negative aspects. Here is the text:\n",
    "{input}\"\"\"\n",
    "\n",
    "negative_template = \"\"\"You are an AI that is designed to find the negative aspects in a text. \\\n",
    "You analyze a text and show the potential downsides. Here is the text:\n",
    "{input}\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt_infos = [\n",
    "    {\n",
    "        \"name\": \"positive\",\n",
    "        \"description\": \"Good for analyzing positive sentiments\",\n",
    "        \"prompt_template\": positive_template,\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"neutral\",\n",
    "        \"description\": \"Good for analyzing neutral sentiments\",\n",
    "        \"prompt_template\": neutral_template,\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"negative\",\n",
    "        \"description\": \"Good for analyzing negative sentiments\",\n",
    "        \"prompt_template\": negative_template,\n",
    "    },\n",
    "]\n",
    "\n",
    "llm = OpenAI()\n",
    "\n",
    "destination_chains = {}\n",
    "for p_info in prompt_infos:\n",
    "    name = p_info[\"name\"]\n",
    "    prompt_template = p_info[\"prompt_template\"]\n",
    "    prompt = PromptTemplate(template=prompt_template, input_variables=[\"input\"])\n",
    "    chain = LLMChain(llm=llm, prompt=prompt)\n",
    "    destination_chains[name] = chain\n",
    "destination_chains"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n",
    "destinations_str = \"\\n\".join(destinations)\n",
    "router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)\n",
    "router_prompt = PromptTemplate(\n",
    "    template=router_template,\n",
    "    input_variables=[\"input\"],\n",
    "    output_parser=RouterOutputParser(),\n",
    ")\n",
    "\n",
    "router_chain = LLMRouterChain.from_llm(llm, router_prompt)\n",
    "\n",
    "chain = MultiPromptChain(\n",
    "    router_chain=router_chain,\n",
    "    destination_chains=destination_chains,\n",
    "    default_chain=destination_chains[\"neutral\"],\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "chain.run(\"I ordered Pizza Salami for 9.99$ and it was awesome!\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "autogpt",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
